package cn.stylefeng.guns.sys.modular.user.service.impl;

import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.guns.core.consts.CommonConstant;
import cn.stylefeng.guns.core.consts.SymbolConstant;
import cn.stylefeng.guns.core.context.constant.ConstantContextHolder;
import cn.stylefeng.guns.core.enums.CommonStatusEnum;
import cn.stylefeng.guns.core.exception.AuthException;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.exception.enums.AuthExceptionEnum;
import cn.stylefeng.guns.core.exception.enums.StatusExceptionEnum;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.login.LoginUserVO;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.core.util.HttpServletUtil;
import cn.stylefeng.guns.core.util.IpAddressUtil;
import cn.stylefeng.guns.core.util.PoiUtil;
import cn.stylefeng.guns.sys.config.SysSmtpConfigProperty;
import cn.stylefeng.guns.sys.core.cache.RedisBackCache;
import cn.stylefeng.guns.sys.core.cache.RedisCache;
import cn.stylefeng.guns.sys.core.enums.AdminTypeEnum;
import cn.stylefeng.guns.sys.modular.auth.constant.Constant;
import cn.stylefeng.guns.sys.modular.auth.service.AuthService;
import cn.stylefeng.guns.sys.modular.auth.util.CertAuthUtil;
import cn.stylefeng.guns.sys.modular.emp.param.SysEmpParam;
import cn.stylefeng.guns.sys.modular.emp.result.SysEmpInfo;
import cn.stylefeng.guns.sys.modular.emp.service.SysEmpService;
import cn.stylefeng.guns.sys.modular.file.service.SysFileInfoService;
import cn.stylefeng.guns.sys.modular.user.entity.SysUser;
import cn.stylefeng.guns.sys.modular.user.entity.SysUserCustom;
import cn.stylefeng.guns.sys.modular.user.entity.UserPermitDevice;
import cn.stylefeng.guns.sys.modular.user.enums.SysUserExceptionEnum;
import cn.stylefeng.guns.sys.modular.user.factory.SysUserFactory;
import cn.stylefeng.guns.sys.modular.user.mapper.SysUserCustomMapper;
import cn.stylefeng.guns.sys.modular.user.mapper.SysUserMapper;
import cn.stylefeng.guns.sys.modular.user.mapper.UserPermitDeviceMapper;
import cn.stylefeng.guns.sys.modular.user.param.SysUserParam;
import cn.stylefeng.guns.sys.modular.user.result.SysUserResult;
import cn.stylefeng.guns.sys.modular.user.service.SysUserDataScopeService;
import cn.stylefeng.guns.sys.modular.user.service.SysUserRoleService;
import cn.stylefeng.guns.sys.modular.user.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;

/**
 * 系统用户service接口实现类
 *
 * @author xuyuxiang
 * @date 2020/3/11 17:49
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private static final Logger LOGGER = org.apache.logging.log4j.LogManager.getLogger(SysUserServiceImpl.class);

    private static final String MODIFY_PASSWORD_TEXT = "【%s】您的验证码是：%s，5分钟内有效，请勿将验证码告知他人。";

    private static final String MODIFY_PASSWORD_TEXT_EN = "[%s] Your verification code is: %s, valid for 5 minutes. Please do not disclose the verification code to others.";

    @Resource
    private SysEmpService sysEmpService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysUserDataScopeService sysUserDataScopeService;

    @Resource
    private SysFileInfoService sysFileInfoService;

    @Resource
    private SysUserMapper sysUserMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RedisBackCache redisBackCache;

    @Autowired
    private AuthService authService;

    @Autowired
    private SysUserCustomMapper sysUserCustomMapper;

    @Autowired
    private UserPermitDeviceMapper userPermitDeviceMapper;

    @Autowired
    private SysSmtpConfigProperty sysSmtpConfigProperty;

    @Override
    public SysUser getUserByCount(String account) {
        // 客服对接
        return sysUserMapper.getOneVSysUser(account);
    }

    @Override
    public SysUser getUserByUserId(Long userId) {
        // 客服对接
        return sysUserMapper.getOneVSysUserById(userId);
    }

    @Override
    public List<SysUser> getUserByEmail(String email) {
        if(StrUtil.isBlank(email)) {
            return null;
        }

        // 客服对接
        return sysUserMapper.getOneVSysUserByEmail(email);
    }

    @Override
    public PageResult<SysUserResult> page(SysUserParam sysUserParam) {
        QueryWrapper<SysUserResult> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(sysUserParam)) {
            //根据关键字模糊查询（姓名，账号，手机号）
            if (ObjectUtil.isNotEmpty(sysUserParam.getSearchValue())) {
                queryWrapper.and(q -> q.like("sys_user.account", sysUserParam.getSearchValue())
                        .or().like("sys_user.name", sysUserParam.getSearchValue())
                        .or().like("sys_user.phone", sysUserParam.getSearchValue()));
            }
            //根据员工所属机构查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getSysEmpParam())) {
                SysEmpParam sysEmpParam = sysUserParam.getSysEmpParam();
                if (ObjectUtil.isNotEmpty(sysEmpParam.getOrgId())) {
                    //查询属于该机构的，或该机构下级所有的人员
                    queryWrapper.and(q -> q.eq("sys_emp.org_id", sysEmpParam.getOrgId())
                            .or().like("sys_org.pids", sysEmpParam.getOrgId()));
                }
            }
            //根据状态查询（0正常 1停用），删除的不会展示在列表
            if (ObjectUtil.isNotEmpty(sysUserParam.getSearchStatus())) {
                queryWrapper.eq("sys_user.status", sysUserParam.getSearchStatus());
            }
        }
        //查询非删除状态，排除超级管理员
        queryWrapper.ne("sys_user.status", CommonStatusEnum.DELETED.getCode())
                .ne("sys_user.admin_type", AdminTypeEnum.SUPER_ADMIN.getCode());

        //如果是超级管理员则获取所有用户，否则只获取其数据范围的用户
        // 客服对接，管理员才有菜单直接可用查看所有用户
//        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
//        if (!superAdmin) {
//            List<Long> dataScope = sysUserParam.getDataScope();
//            if (ObjectUtil.isEmpty(dataScope)) {
//                return new PageResult<>(new Page<>());
//            } else {
//                Set<Long> dataScopeSet = CollectionUtil.newHashSet(dataScope);
//                queryWrapper.in("sys_emp.org_id", dataScopeSet);
//            }
//        }
        return new PageResult<>(this.baseMapper.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<SysUserResult> getAllUser(SysUserParam sysUserParam) {
        QueryWrapper<SysUserResult> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(sysUserParam)) {
            //根据关键字模糊查询（姓名，账号，手机号）
            if (ObjectUtil.isNotEmpty(sysUserParam.getSearchValue())) {
                queryWrapper.and(q -> q.like("sys_user.account", sysUserParam.getSearchValue())
                        .or().like("sys_user.name", sysUserParam.getSearchValue())
                        .or().like("sys_user.phone", sysUserParam.getSearchValue()));
            }
            // 账户查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getAccount())) {
                queryWrapper.and(q -> q.like("sys_user.account", sysUserParam.getAccount()));
            }
            // 用户名查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getName())) {
                queryWrapper.and(q -> q.like("sys_user.name", sysUserParam.getName()));
            }
            //根据员工所属机构查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getSysEmpParam())) {
                SysEmpParam sysEmpParam = sysUserParam.getSysEmpParam();
                if (ObjectUtil.isNotEmpty(sysEmpParam.getOrgId())) {
                    //查询属于该机构的，或该机构下级所有的人员
                    queryWrapper.and(q -> q.eq("sys_emp.org_id", sysEmpParam.getOrgId())
                            .or().like("sys_org.pids", sysEmpParam.getOrgId()));
                }
            }
            //根据状态查询（0正常 1停用），删除的不会展示在列表
            if (ObjectUtil.isNotEmpty(sysUserParam.getSearchStatus())) {
                queryWrapper.eq("sys_user.status", sysUserParam.getSearchStatus());
            }
        }
        //查询非删除状态，排除超级管理员
        queryWrapper.ne("sys_user.status", CommonStatusEnum.DELETED.getCode())
                .ne("sys_user.admin_type", AdminTypeEnum.SUPER_ADMIN.getCode());

        //如果是超级管理员则获取所有用户，否则只获取其数据范围的用户
        // 客服对接，管理员才有菜单直接可用查看所有用户
//        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
//        if (!superAdmin) {
//            List<Long> dataScope = sysUserParam.getDataScope();
//            if (ObjectUtil.isEmpty(dataScope)) {
//                return new PageResult<>(new Page<>());
//            } else {
//                Set<Long> dataScopeSet = CollectionUtil.newHashSet(dataScope);
//                queryWrapper.in("sys_emp.org_id", dataScopeSet);
//            }
//        }
        return this.baseMapper.getAllUser(queryWrapper);
    }

    @Override
    public List<Dict> list(SysUserParam sysUserParam) {
        List<Dict> dictList = CollectionUtil.newArrayList();
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotNull(sysUserParam)) {
            //根据账号，姓名模糊查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getAccount())) {
                queryWrapper.and(i -> i.like(SysUser::getAccount, sysUserParam.getAccount())
                        .or().like(SysUser::getName, sysUserParam.getAccount()));
            }
        }
        //查询正常状态，排除超级管理员
        queryWrapper.eq(SysUser::getStatus, CommonStatusEnum.ENABLE.getCode())
                .ne(SysUser::getAdminType, AdminTypeEnum.SUPER_ADMIN.getCode());
        this.list(queryWrapper).forEach(sysUser -> {
            Dict dict = Dict.create();
            dict.put("id", sysUser.getId().toString());
            dict.put("firstName", sysUser.getName() + SymbolConstant.LEFT_SQUARE_BRACKETS
                    + sysUser.getAccount() + SymbolConstant.RIGHT_SQUARE_BRACKETS);
            dictList.add(dict);
        });
        return dictList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(SysUserParam sysUserParam) {
//        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
//        if (!superAdmin) {
//            List<Long> dataScope = sysUserParam.getDataScope();
//            //获取添加的用户的所属机构
//            Long orgId = sysUserParam.getSysEmpParam().getOrgId();
//            //数据范围为空
//            if (ObjectUtil.isEmpty(dataScope)) {
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            } else if (!dataScope.contains(orgId)) {
//                //所添加的用户的所属机构不在自己的数据范围内
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            }
//        }
        String accountEn = sysUserParam.getAccount();
        String pwdEn = sysUserParam.getPassword();
        // RAS2048解密
        try {
            sysUserParam.setAccount(new String(decrypt(Base64.getDecoder().decode(accountEn), Constant.PRIVATE_KEY)));
            sysUserParam.setPassword(new String(decrypt(Base64.getDecoder().decode(pwdEn), Constant.PRIVATE_KEY)));
        } catch (Exception e) {
            e.printStackTrace();
            throw new AuthException(AuthExceptionEnum.DECRYPT_ERROR);
        }
        // 判断用户是否已经存在
        checkParam(sysUserParam, false);

        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(sysUserParam, sysUser);
        SysUserFactory.fillAddCommonUserInfo(sysUser);
        sysUser.setPassword(BCrypt.hashpw(sysUser.getPassword(), BCrypt.gensalt()));
        this.save(sysUser);
        Long sysUserId = sysUser.getId();
        //增加员工信息
        SysEmpParam sysEmpParam = sysUserParam.getSysEmpParam();
        sysEmpParam.setId(sysUserId);
        sysEmpService.addOrUpdate(sysEmpParam);

        // 管理端手动添加的用户在client端具备全部客户的查询权限
        SysUserCustom entity = new SysUserCustom();
        entity.setCustomId(1L);
        entity.setUserId(sysUserId);
        entity.setCreateTime(new Date());
        sysUserCustomMapper.insert(entity);
    }

    public static byte[] decrypt(byte[] str, String privateKey) throws Exception {
        byte[] decoded = Base64.getDecoder().decode(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(2, priKey);
        return cipher.doFinal(str);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        //不能删除超级管理员
        if (AdminTypeEnum.SUPER_ADMIN.getCode().equals(sysUser.getAdminType())) {
            throw new ServiceException(SysUserExceptionEnum.USER_CAN_NOT_DELETE_ADMIN);
        }
//        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
//        if (!superAdmin) {
//            List<Long> dataScope = sysUserParam.getDataScope();
//            //获取要删除的用户的所属机构
//            SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
//            Long orgId = sysEmpInfo.getOrgId();
//            //数据范围为空
//            if (ObjectUtil.isEmpty(dataScope)) {
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            } else if (!dataScope.contains(orgId)) {
//                //所要删除的用户的所属机构不在自己的数据范围内
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            }
//        }
        sysUser.setStatus(CommonStatusEnum.DELETED.getCode());
        this.updateById(sysUser);
        Long id = sysUser.getId();
        //删除该用户对应的员工表信息
        sysEmpService.deleteEmpInfoByUserId(id);

        //删除该用户对应的用户-角色表关联信息
        sysUserRoleService.deleteUserRoleListByUserId(id);

        //删除该用户对应的用户-数据范围表关联信息
        sysUserDataScopeService.deleteUserDataScopeListByUserId(id);

        // 撤销证书
        if (StringUtils.isNotBlank(sysUser.getCertificatePath())){
            CertAuthUtil.revokeCert(sysUser.getCertificatePath());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        checkParam(sysUserParam, true);
//        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
//        if (!superAdmin) {
//            List<Long> dataScope = sysUserParam.getDataScope();
//            //获取要编辑的用户的所属机构
//            Long orgId = sysUserParam.getSysEmpParam().getOrgId();
//            //数据范围为空
//            if (ObjectUtil.isEmpty(dataScope)) {
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            } else if (!dataScope.contains(orgId)) {
//                //所要编辑的用户的所属机构不在自己的数据范围内
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            }
//        }

        BeanUtil.copyProperties(sysUserParam, sysUser);
        //不能修改状态，用修改状态接口修改状态
        sysUser.setStatus(null);
        //设置密码
//        SysUserFactory.fillBaseUserInfo(sysUser);
        this.updateById(sysUser);
        Long sysUserId = sysUser.getId();
        //编辑员工信息
        SysEmpParam sysEmpParam = sysUserParam.getSysEmpParam();
        BeanUtil.copyProperties(sysUserParam, sysEmpParam);
        sysEmpParam.setId(sysUserId);
        sysEmpService.addOrUpdate(sysEmpParam);
    }

    @Override
    public SysUserResult detail(SysUserParam sysUserParam) {
        SysUserResult sysUserResult = new SysUserResult();
        //获取系统用户
        SysUser sysUser = this.querySysUser(sysUserParam);
        BeanUtil.copyProperties(sysUser, sysUserResult);
        //获取对应员工信息
        SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
        //设置员工信息
        sysUserResult.setSysEmpInfo(sysEmpInfo);
        return sysUserResult;
    }

    @Override
    public void changeStatus(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        //不能修改超级管理员状态
        if (AdminTypeEnum.SUPER_ADMIN.getCode().equals(sysUser.getAdminType())) {
            throw new ServiceException(SysUserExceptionEnum.USER_CAN_NOT_UPDATE_ADMIN);
        }

        Long id = sysUser.getId();

        Integer status = sysUserParam.getStatus();
        //校验状态在不在枚举值里
        CommonStatusEnum.validateStatus(status);

        //更新枚举，更新只能更新未删除状态的
        LambdaUpdateWrapper<SysUser> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SysUser::getId, id)
                .and(i -> i.ne(SysUser::getStatus, CommonStatusEnum.DELETED.getCode()))
                .set(SysUser::getStatus, status);
        boolean update = this.update(updateWrapper);
        if (!update) {
            throw new ServiceException(StatusExceptionEnum.UPDATE_STATUS_ERROR);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void grantRole(SysUserParam sysUserParam) {
//        SysUser sysUser = this.querySysUser(sysUserParam);
//        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
//        if (!superAdmin) {
//            List<Long> dataScope = sysUserParam.getDataScope();
//            //获取要授权角色的用户的所属机构
//            SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
//            Long orgId = sysEmpInfo.getOrgId();
//            //数据范围为空
//            if (ObjectUtil.isEmpty(dataScope)) {
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            } else if (!dataScope.contains(orgId)) {
//                //所要授权角色的用户的所属机构不在自己的数据范围内
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            }
//        }
        sysUserRoleService.grantRole(sysUserParam);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void grantData(SysUserParam sysUserParam) {
//        SysUser sysUser = this.querySysUser(sysUserParam);
//        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
//        if (!superAdmin) {
//            List<Long> dataScope = sysUserParam.getDataScope();
//            //获取要授权数据的用户的所属机构
//            SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
//            Long orgId = sysEmpInfo.getOrgId();
//            //数据范围为空
//            if (ObjectUtil.isEmpty(dataScope)) {
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            } else if (!dataScope.contains(orgId)) {
//                //所要授权数据的用户的所属机构不在自己的数据范围内
//                throw new PermissionException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
//            }
//        }
        sysUserDataScopeService.grantData(sysUserParam);
    }

    @Override
    public void updateInfo(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        BeanUtil.copyProperties(sysUserParam, sysUser);
        this.updateById(sysUser);
    }

    @Override
    public void updatePwd(SysUserParam sysUserParam) {
        String password = sysUserParam.getPassword();
        String newPassword = sysUserParam.getNewPassword();
        try {
            // RAS2048解密
            if(StrUtil.isNotEmpty(password)) {
                password = new String(decrypt(Base64.getDecoder().decode(password), Constant.PRIVATE_KEY));
                sysUserParam.setPassword(password);
            }

            if(StrUtil.isNotEmpty(newPassword)) {
                newPassword = new String(decrypt(Base64.getDecoder().decode(newPassword), Constant.PRIVATE_KEY));
                sysUserParam.setNewPassword(newPassword);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new AuthException(CommonConstant.DECRYPT_ERROR, sysUserParam.getLocale());
        }

        SysUser sysUser = this.querySysUser(sysUserParam);
        //密码与用户名相同
        if (sysUserParam.getNewPassword().equals(sysUser.getAccount())) {
            if("en".equals(sysUserParam.getLocale())) {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_REPEAT_ACCOUNT_EN);
            } else {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_REPEAT_ACCOUNT);
            }
        }
        //密码与用户名倒写相同
        if (sysUserParam.getNewPassword().equals(StrUtil.reverse(sysUser.getAccount()))) {
            if("en".equals(sysUserParam.getLocale())) {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_REPEAT_ACCOUNT_REVERSE_EN);
            } else {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_REPEAT_ACCOUNT_REVERSE);
            }
        }
        //新密码与原密码相同
        if (sysUserParam.getNewPassword().equals(sysUserParam.getPassword())) {
            if("en".equals(sysUserParam.getLocale())) {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_REPEAT_EN);
            } else {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_REPEAT);
            }
        }
        HttpServletRequest request = HttpServletUtil.getRequest();
        String ip = "";
        if (ObjectUtil.isNotNull(request)) {
            ip = IpAddressUtil.getIp(request);
        }
        String account = sysUser.getAccount();
        String userCheckPwdKey = CommonConstant.USER_CHECK_PWD_PREFIX + account + "_" + ip;
        //原密码错误
        if (!BCrypt.checkpw(sysUserParam.getPassword(), sysUser.getPassword())) {
            Integer failNum = 0;
            if (redisCache.hasKey(userCheckPwdKey)) {
                failNum = Integer.parseInt(redisCache.get(userCheckPwdKey));
            }

            //判断用户是否输错次数过多
            if (failNum >= CommonConstant.MAX_LOGIN_FAILED_LOCK_COUNT-1) {
                if (isInUpdPwdFailTimeScope(sysUser)) {
                    // 用户输错次数过多锁定账号
                    redisCache.put(CommonConstant.USER_LOCK_PREFIX + account, account, CommonConstant.USER_LOCKED_TIME);
                    redisBackCache.put(CommonConstant.USER_LOCK_PREFIX + account, account, 5 * 60);
                    log.info(">>> [{}] 用户密码输错次数过多，符合锁定条件, 已被锁定!", account);

                    redisCache.remove(userCheckPwdKey);
                    authService.logout();
                    if("en".equals(sysUserParam.getLocale())) {
                        throw new ServiceException(SysUserExceptionEnum.TOO_MANY_USER_PWD_CHECK_ERROR_EN);
                    } else {
                        throw new ServiceException(SysUserExceptionEnum.TOO_MANY_USER_PWD_CHECK_ERROR);
                    }
                } else {
                    //清除登录失败标志信息
                    unLockUserClearUpdPwdFailFlag(account,userCheckPwdKey);
                    log.info(">>> [{}] 用户不符合连续时间内密码输错次数过多条件, 已清除锁定标志!", account);
                }

            }else{
                if (failNum == 0) {
                    //第一次输入错误时间为后续连续判断准备
                    redisCache.put(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + account, String.valueOf(new Date()), CommonConstant.LOGIN_FAILED_CYCLE);
                    redisBackCache.put(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + account, String.valueOf(new Date()), (int) CommonConstant.LOGIN_FAILED_CYCLE);
                }
                redisCache.put(userCheckPwdKey, String.valueOf(failNum+1), CommonConstant.LOGIN_FAILED_CYCLE);
                redisBackCache.put(userCheckPwdKey, String.valueOf(failNum+1), 20 * 60);
                log.info(">>> [{}] 用户不符合连续时间内密码输错次数过多条件, 登录失败次数: {} 次", account, failNum + 1);
            }

            if("en".equals(sysUserParam.getLocale())) {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_ERROR_EN);
            } else {
                throw new ServiceException(SysUserExceptionEnum.USER_PWD_ERROR);
            }
        } else {
            // 验证通过后移除
            if (redisCache.hasKey(userCheckPwdKey)) {
                redisCache.remove(userCheckPwdKey);
            }
        }
        sysUser.setPassword(BCrypt.hashpw(sysUserParam.getNewPassword(), BCrypt.gensalt()));
        sysUser.setLastUpdPwdTime(new Date());
        this.updateById(sysUser);
    }

    public String encryptEmail(String email) {
        if(StrUtil.isEmpty(email)) {
            return email;
        }
        if(email.indexOf("@") > 0) {
            String suffix = email.substring(email.indexOf("@"));
            email = email.substring(0, email.indexOf("@"));
            int length = email.length();
            if(length > 2 && length <= 4 ) {
                email = email.substring(0,1) + "*" + email.substring(2);
            } else if(length <= 6) {
                email = email.substring(0,2) + "**" + email.substring(4);
            } else {
                email = email.substring(0,3) + "***" + email.substring(6);
            }

            return email + suffix;
        }

        return email;
    }

    @Override
    public ResponseData<?> getVerifyCode(String account, String locale) {
        try {
            if (StringUtils.isBlank(account)) {
                if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                    return ResponseData.error("Account cannot be empty");
                } else {
                    return ResponseData.error("账号不能为空");
                }
            }

            if(!authService.checkCountLimit("request")) {
                if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                    return ResponseData.error("The operation is too frequent, please try again in 5 minutes");
                } else {
                    return ResponseData.error("操作太频繁，请5分钟之后再尝试");
                }
            }

            // RAS2048解密
            try {
                account = new String(decrypt(Base64.getDecoder().decode(account), Constant.PRIVATE_KEY));
            } catch (Exception e) {
                LOGGER.error("账号解密异常, {}", e.getMessage());
                if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                    return ResponseData.error("Account abnormality");
                } else {
                    return ResponseData.error("账号异常");
                }
            }

            SysUser sysUser = getUserByCount(account);
            if (ObjectUtil.isEmpty(sysUser)) {
                // 此时的账号可能是邮箱，使用邮箱查询登录用户的信息
                List<SysUser> userList = getUserByEmail(account);
                if(CollectionUtil.isNotEmpty(userList)) {
                    sysUser = userList.get(0);
                    if(sysUser != null) {
                        account = sysUser.getAccount();
                    } else {
                        if("en".equals(locale)) {
                            return ResponseData.error("User does not exist");
                        } else {
                            return ResponseData.error("用户不存在");
                        }
                    }
                } else {
                    if("en".equals(locale)) {
                        return ResponseData.error("User does not exist");
                    } else {
                        return ResponseData.error("用户不存在");
                    }
                }
            }

            if(!"01".equals(sysUser.getSourceType())) {
                if("en".equals(locale)) {
                    return ResponseData.error("This user is an online system user.Please go to the online system to change the password");
                } else {
                    return ResponseData.error("该用户是线上系统用户，请到线上系统去修改密码");
                }
            }

            String email = sysUser.getEmail();
            if(StrUtil.isEmpty(email)) {
                if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                    return ResponseData.error("Due to the user's lack of email information, the verification code cannot be received; To change the password, please contact the administrator to reset the password");
                } else {
                    return ResponseData.error("由于该用户信息中没有填写邮箱，无法接收验证码；若要修改密码，请联系管理员重置密码");
                }
            }

            if(!authService.checkEmailLimit(email)) {
                if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                    return ResponseData.error("The same email can only send a verification code once within 5 minutes");
                } else {
                    return ResponseData.error("同一邮箱在5分钟内仅可以发送一次验证码");
                }
            }

            if(!authService.checkIpLimit("code")) {
                if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                    return ResponseData.error("The operation is too frequent, please try again in 5 minutes");
                } else {
                    return ResponseData.error("操作太频繁，请5分钟之后再尝试");
                }
            }

            RandomGenerator randomGenerator = new RandomGenerator("0123456789", 6);
            String code = randomGenerator.generate();
            // 发送验证码邮件
            if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                if(!authService.sendSmtpEmail(email,null,"Verification code",MODIFY_PASSWORD_TEXT_EN.formatted(sysSmtpConfigProperty.getAppName(),code))){
                    if (!authService.sendEmail("Verification code", MODIFY_PASSWORD_TEXT_EN.formatted(code), email, null)) {
                        return ResponseData.error("Email service exception, verification code sending failed. Please contact the administrator");
                    }
                }
            } else {
                if(!authService.sendSmtpEmail(email,null,"验证码",MODIFY_PASSWORD_TEXT.formatted(sysSmtpConfigProperty.getAppName(),code))) {
                    if (!authService.sendEmail("验证码", MODIFY_PASSWORD_TEXT.formatted(code), email, null)) {
                        return ResponseData.error("邮箱服务异常，验证码发送失败，请联系管理员");
                    }
                }
            }

            // redis记录
            String key = String.join("_", CommonConstant.MODIFY_PASSWORD_CODE, account, email);
            redisCache.put(key, code, 5 * 60L);
            redisBackCache.put(key, code, 5 * 60);
            email = encryptEmail(email);
            if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                return ResponseData.success("The verification code has been sent to the email " + email + " Please log in to this email to obtain the verification code");
            } else {
                return ResponseData.success("验证码已发送至邮箱" + email + "，请登录该邮箱获取验证码");
            }
        } catch (Exception e) {
            LOGGER.error("获取验证码异常, {}", e);
            if(StrUtil.isNotBlank(locale) && "en".equals(locale)) {
                return ResponseData.error("Exception in obtaining verification code. Please contact the administrator");
            } else {
                return ResponseData.error("获取验证码异常，请联系管理员");
            }
        }
    }

    @Override
    public void grantPermitDevice(SysUserParam sysUserParam) {

        String permitDevice = sysUserParam.getPermitDevice();
        if(StrUtil.isNotBlank(permitDevice)){
            UserPermitDevice userPermitDevice = userPermitDeviceMapper.getPermitDeviceByUserId(sysUserParam.getId());
            if(null!=userPermitDevice){
                // 更新
                userPermitDevice.setPermitDevice(sysUserParam.getPermitDevice());
                userPermitDeviceMapper.updateById(userPermitDevice);
            }else{
                // 插入
                userPermitDevice = new UserPermitDevice();
                userPermitDevice.setUserId(sysUserParam.getId());
                userPermitDevice.setPermitDevice(sysUserParam.getPermitDevice());
                userPermitDeviceMapper.insert(userPermitDevice);
            }
        }else{
            // 删除设备标识信息
            userPermitDeviceMapper.deleteByUserId(sysUserParam.getId());
        }
    }

    @Override
    public UserPermitDevice permitDeviceDetail(SysUserParam sysUserParam) {
        //获取设备标识信息
        UserPermitDevice userPermitDevice = userPermitDeviceMapper.getPermitDeviceByUserId(sysUserParam.getId());

        return userPermitDevice;
    }

    @Override
    public ResponseData<?> modifyPwd(SysUserParam sysUserParam) {
        String locale = "zh";
        try {
            if(sysUserParam != null && StrUtil.isNotEmpty(sysUserParam.getLocale())) {
                locale = sysUserParam.getLocale();
            }

            if (Objects.isNull(sysUserParam) || StringUtils.isAnyBlank(sysUserParam.getAccount(), sysUserParam.getPassword(), sysUserParam.getVerifyCode(), sysUserParam.getCode())) {
                if("en".equals(locale)) {
                    return ResponseData.error("Account,emailVerifyCode,password,code information cannot be empty");
                } else {
                    return ResponseData.error("账号、邮箱验证码、密码、验证码等信息不能为空");
                }
            }

            HttpServletRequest request = HttpServletUtil.getRequest();
            String ip = "";
            if (ObjectUtil.isNotNull(request)) {
                ip = IpAddressUtil.getIp(request);
            }

            String redisCaptchaKey = CommonConstant.CAPTCHA_CODE + "_" + ip;
            String redisCaptcha = redisCache.get(redisCaptchaKey);
            if (StrUtil.isBlank(redisCaptcha)) {
                if("zh".equals(locale)) {
                    return ResponseData.error("验证码已经过期，请刷新验证码");
                } else {
                    return ResponseData.error("Verification has expired, please refresh the verification code again");
                }
            }
            // 根据安全要求校验码在此处需要置为无效
            redisCache.remove(redisCaptchaKey);
            if (!StrUtil.equals(sysUserParam.getCode().trim(), redisCaptcha)) {
                if("zh".equals(locale)) {
                    return ResponseData.error("验证码错误");
                } else {
                    return ResponseData.error("Verification code error");
                }
            }

            // RAS2048解密
            String account = null, password = null;
            try {
                account = new String(decrypt(Base64.getDecoder().decode(sysUserParam.getAccount()), Constant.PRIVATE_KEY));
                password = new String(decrypt(Base64.getDecoder().decode(sysUserParam.getPassword()), Constant.PRIVATE_KEY));
            } catch (Exception e) {
                LOGGER.error("账号、密码解密异常,{}", e.getMessage());
                if("en".equals(locale)) {
                    return ResponseData.error("Account and password decryption exception");
                } else {
                    return ResponseData.error("账号、密码解密异常");
                }
            }

            SysUser sysUser = getUserByCount(account);
            // 用户不存在，账号或密码错误
            if (ObjectUtil.isEmpty(sysUser)) {
                // 此时的账号可能是邮箱，使用邮箱查询登录用户的信息
                List<SysUser> userList = getUserByEmail(account);
                if(CollectionUtil.isNotEmpty(userList)) {
                    sysUser = userList.get(0);
                    if(sysUser != null) {
                        account = sysUser.getAccount();
                    } else {
                        if("en".equals(locale)) {
                            return ResponseData.error("User does not exist");
                        } else {
                            return ResponseData.error("用户不存在");
                        }
                    }
                } else {
                    if("en".equals(locale)) {
                        return ResponseData.error("User does not exist");
                    } else {
                        return ResponseData.error("用户不存在");
                    }
                }
            }

            if(!"01".equals(sysUser.getSourceType())) {
                if("en".equals(locale)) {
                    return ResponseData.error("This user is an online system user.Please go to the online system to change the password");
                } else {
                    return ResponseData.error("该用户是线上系统用户，请到线上系统去修改密码");
                }
            }

            String email = sysUser.getEmail();
            // 校验验证码
            String key = String.join("_", CommonConstant.MODIFY_PASSWORD_CODE, account, email);
            String codeBack = redisBackCache.get(key);
            String code = redisCache.hasKey(key) ? redisCache.get(key) : StringUtils.isNotBlank(codeBack) ? codeBack : null;
            if(ObjectUtil.isEmpty(code)) {
                if("en".equals(locale)) {
                    return ResponseData.error("The email verification code has expired and become invalid");
                } else {
                    return ResponseData.error("邮箱验证码已过期失效");
                }
            } else {
                if (!sysUserParam.getVerifyCode().equals(code)) {
                    if("en".equals(locale)) {
                        return ResponseData.error("Email verification code error");
                    } else {
                        return ResponseData.error("邮箱验证码错误");
                    }
                }
            }

            // 密码与用户名相同
            if (password.equals(account)) {
                if("en".equals(locale)) {
                    return ResponseData.error("The new password is the same as the username, please reset it");
                } else {
                    return ResponseData.error("新密码与用户名相同，请重新设置");
                }
            }

            // 密码与用户名倒写相同
            if (password.equals(StrUtil.reverse(account))) {
                if("en".equals(locale)) {
                    return ResponseData.error("The new password and the username are reversed, please reset it");
                } else {
                    return ResponseData.error("新密码与用户名倒写相同，请重新设置");
                }
            }

            sysUser.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
            sysUser.setLastUpdPwdTime(new Date());
            this.updateById(sysUser);
            // 移除缓存
            redisCache.remove(key);
            redisBackCache.remove(key);
            return ResponseData.success();
        } catch (Exception e) {
            if("en".equals(locale)) {
                return ResponseData.error("Password reset failed, please contact the administrator");
            } else {
                return ResponseData.error("重置密码失败，请联系管理员");
            }
        }
    }

    /**
     * 判断用户登录失败时间在规定范围内
     *
     * @param sysUser 用户
     * @return 结果 true 在范围内
     */
    private boolean isInUpdPwdFailTimeScope(SysUser sysUser) {
        String account = sysUser.getAccount();
        String lastLoginFailTimeStr = "";
        if(redisCache.hasKey(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + account)){
            lastLoginFailTimeStr = redisCache.get(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + account);
        }else if(StrUtil.isNotEmpty(redisBackCache.get(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + account)) ){
            lastLoginFailTimeStr = redisBackCache.get(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + account);
        }else{
            return false;
        }
        Date lastLoginFailTime = DateUtil.parse(lastLoginFailTimeStr);
        return DateUtil.between(lastLoginFailTime,DateUtil.date().toJdkDate(),DateUnit.SECOND)<= CommonConstant.LOGIN_FAILED_CYCLE;
    }

    public boolean unLockUserClearUpdPwdFailFlag(String expUserAccount,String userCheckPwdKey) {
        // 客服对接
        if(redisCache.hasKey(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + expUserAccount)){
            redisCache.remove(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + expUserAccount);
        }
        if(redisCache.hasKey(userCheckPwdKey)){
            redisCache.remove(userCheckPwdKey);
        }

        if(StrUtil.isNotEmpty(redisBackCache.get(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + expUserAccount))) {
            redisBackCache.remove(CommonConstant.USER_UPD_PWD_FIRST_FAIL_TIME + expUserAccount);
        }
        if(StrUtil.isNotEmpty(redisBackCache.get(userCheckPwdKey))){
            redisBackCache.remove(userCheckPwdKey);
        }
        return true;
    }

    @Override
    public List<Long> getUserDataScopeIdList(Long userId, Long orgId) {
        Set<Long> userDataScopeIdSet = CollectionUtil.newHashSet();
        if (ObjectUtil.isAllNotEmpty(userId, orgId)) {

            //获取该用户对应的数据范围集合
            List<Long> userDataScopeIdListForUser = sysUserDataScopeService.getUserDataScopeIdList(userId);

            //获取该用户的角色对应的数据范围集合
            List<Long> userDataScopeIdListForRole = sysUserRoleService.getUserRoleDataScopeIdList(userId, orgId);

            userDataScopeIdSet.addAll(userDataScopeIdListForUser);
            userDataScopeIdSet.addAll(userDataScopeIdListForRole);
        }
        return CollectionUtil.newArrayList(userDataScopeIdSet);
    }

    @Override
    public String getNameByUserId(Long userId) {
        SysUser sysUser = this.getById(userId);
        if (ObjectUtil.isNull(sysUser)) {
            throw new ServiceException(SysUserExceptionEnum.USER_NOT_EXIST);
        }
        return sysUser.getName();
    }

    @Override
    public List<Long> ownRole(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        return sysUserRoleService.getUserRoleIdList(sysUser.getId());
    }

    @Override
    public List<Long> ownData(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        return sysUserDataScopeService.getUserDataScopeIdList(sysUser.getId());
    }

    @Override
    public void checkUserPwd(SysUserParam sysUserParam) {
        String password = "";
        try {
            password = new String(decrypt(Base64.getDecoder().decode(sysUserParam.getPassword()), Constant.PRIVATE_KEY));
        } catch (Exception e) {
            e.printStackTrace();
            throw new AuthException(AuthExceptionEnum.DECRYPT_ERROR);
        }
        HttpServletRequest request = HttpServletUtil.getRequest();
        String ip = "";
        if (ObjectUtil.isNotNull(request)) {
            ip = IpAddressUtil.getIp(request);
        }

        SysUser sysUser = this.getById(sysUserParam.getId());
        String userCheckPwdKey = CommonConstant.USER_CHECK_PWD_PREFIX + sysUser.getAccount() + "_" + ip;

        if (!BCrypt.checkpw(password, sysUser.getPassword())) {
            Integer failNum = 1;
            if (redisCache.hasKey(userCheckPwdKey)) {
                failNum = Integer.parseInt(redisCache.get(userCheckPwdKey)) + 1;
            }
            redisCache.put(userCheckPwdKey, String.valueOf(failNum), CommonConstant.LOGIN_FAILED_CYCLE);
            redisBackCache.put(userCheckPwdKey, String.valueOf(failNum), 20 * 60);
            //判断用户是否输错次数过多
            if (failNum >= CommonConstant.MAX_LOGIN_FAILED_LOCK_COUNT) {
                redisCache.remove(userCheckPwdKey);
                throw new AuthException(SysUserExceptionEnum.TOO_MANY_USER_PWD_CHECK_ERROR);
            }
            throw new ServiceException(SysUserExceptionEnum.USER_PWD_CHECK_ERROR);
        } else {
            // 验证通过后移除
            if (redisCache.hasKey(userCheckPwdKey)) {
                redisCache.remove(userCheckPwdKey);
            }
        }
    }

    @Override
    public void resetPwd(SysUserParam sysUserParam) {
        String password = ConstantContextHolder.getDefaultPassWord();
        this.lambdaUpdate()
                .eq(SysUser::getId, sysUserParam.getId())
                .set(SysUser::getLastUpdPwdTime, null)
                .set(SysUser::getPassword, BCrypt.hashpw(password, BCrypt.gensalt()))
                .update();
    }

    @Override
    public void updateAvatar(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        Long avatar = sysUserParam.getAvatar();
        sysFileInfoService.assertFile(avatar);
        sysUser.setAvatar(avatar);
        this.updateById(sysUser);
    }

    @Override
    public void export(SysUserParam sysUserParam) {
        List<SysUser> list = this.list();
        PoiUtil.exportExcelWithStream("GunsUsers.xls", SysUser.class, list);
    }

    @Override
    public List<Dict> selector(SysUserParam sysUserParam) {
        List<Dict> dictList = CollectionUtil.newArrayList();
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotNull(sysUserParam)) {
            //根据姓名模糊查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getName())) {
                queryWrapper.like(SysUser::getName, sysUserParam.getName());
            }
        }
        //查询非删除状态，排除超级管理员
        queryWrapper.ne(SysUser::getStatus, CommonStatusEnum.DELETED.getCode())
                .ne(SysUser::getAdminType, AdminTypeEnum.SUPER_ADMIN.getCode());
        this.list(queryWrapper).forEach(sysUser -> {
            Dict dict = Dict.create();
            dict.put(CommonConstant.ID, sysUser.getId());
            dict.put(CommonConstant.NAME, sysUser.getName());
            dictList.add(dict);
        });
        return dictList;
    }

    @Override
    public List<SysUser> findByOrgId(Long orgId) {
        return sysUserMapper.findByOrgId(orgId);
    }

    /**
     * 校验参数，检查是否存在相同的账号
     *
     * @author xuyuxiang
     * @date 2020/3/27 16:04
     */
    private void checkParam(SysUserParam sysUserParam, boolean isExcludeSelf) {
        Long id = sysUserParam.getId();
        String account = sysUserParam.getAccount();
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getAccount, account)
                .ne(SysUser::getStatus, CommonStatusEnum.DELETED.getCode());
        //是否排除自己，如果是则查询条件排除自己id
        if (isExcludeSelf) {
            queryWrapper.ne(SysUser::getId, id);
        }
        int countByAccount = (int) this.count(queryWrapper);
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            throw new ServiceException(SysUserExceptionEnum.USER_ACCOUNT_REPEAT);
        }
    }

    /**
     * 获取系统用户
     *
     * @author xuyuxiang
     * @date 2020/3/26 9:54
     */
    private SysUser querySysUser(SysUserParam sysUserParam) {
        SysUser sysUser = this.getUserByUserId(sysUserParam.getId());
        if (ObjectUtil.isNull(sysUser)) {
            throw new ServiceException(SysUserExceptionEnum.USER_NOT_EXIST);
        }
        return sysUser;
    }

    /**
     * 获取登录用户的基础信息
     *
     * @param userId
     * @return
     */
    @Override
    public LoginUserVO findLoginUserInfoById(Long userId) {
        return this.baseMapper.findLoginUserInfoById(userId);
    }

    @Override
    public void userLoginFailCountIncrement(String account) {
        this.baseMapper.userLoginFailCountIncrement(account);
    }

    @Override
    public boolean unLockUserClearLoginFailFlag(String expUserAccount) {
//        return this.lambdaUpdate()
//                .eq(SysUser::getAccount, expUserAccount)
//                .set(SysUser::getStatus, CommonStatusEnum.ENABLE.getCode())
//                .set(SysUser::getLoginFailCount, 0)
//                .set(SysUser::getFirstLoginFailTime, null)
//                .update();
        // 客服对接
        if(redisCache.hasKey(CommonConstant.USER_LOGIN_FIRST_FAIL_TIME + expUserAccount)){
            redisCache.remove(CommonConstant.USER_LOGIN_FIRST_FAIL_TIME + expUserAccount);
        }
        if(redisCache.hasKey(CommonConstant.USER_LOGIN_FAIL_COUNT + expUserAccount)){
            redisCache.remove(CommonConstant.USER_LOGIN_FAIL_COUNT + expUserAccount);
        }

        if(StrUtil.isNotEmpty(redisBackCache.get(CommonConstant.USER_LOGIN_FIRST_FAIL_TIME + expUserAccount))) {
            redisBackCache.remove(CommonConstant.USER_LOGIN_FIRST_FAIL_TIME + expUserAccount);
        }
        if(StrUtil.isNotEmpty(redisBackCache.get(CommonConstant.USER_LOGIN_FAIL_COUNT + expUserAccount))){
            redisBackCache.remove(CommonConstant.USER_LOGIN_FAIL_COUNT + expUserAccount);
        }
        return true;
    }

    @Override
    public ResponseData<?> isOverUpdatePwdTimeScope(SysUserParam sysUserParam) {
        String account = "";
        try {
            account = new String(decrypt(Base64.getDecoder().decode(sysUserParam.getAccount()), Constant.PRIVATE_KEY));
        } catch (Exception e) {
            e.printStackTrace();
            throw new AuthException(AuthExceptionEnum.DECRYPT_ERROR);
        }

        SysUser sysUser = this.getUserByCount(account);
        if(ObjectUtil.isEmpty(sysUser)) {
            List<SysUser> sysUserList = this.getUserByEmail(account);
            if(CollectionUtil.isNotEmpty(sysUserList)) {
                sysUser = sysUserList.get(0);
            }
        }

        if (ObjectUtil.isNull(sysUser) || ObjectUtil.isNull(sysUser.getLastUpdPwdTime())) {
            if(sysUserParam != null && "en".equals(sysUserParam.getLocale())) {
                return ResponseData.error("You have not changed your password yet. Please change your password promptly!");
            } else {
                return ResponseData.error("您还没有修改过密码，请及时修改密码！");
            }
        }

        Long overDays = DateUtil.between(sysUser.getLastUpdPwdTime(), DateUtil.date().toJdkDate(), DateUnit.DAY) - CommonConstant.LAST_UPD_PWD_SCOPE;
        if (overDays > 0) {
            if(sysUserParam != null && "en".equals(sysUserParam.getLocale())) {
                return ResponseData.error("The password has expired for " + overDays + " days, please change it in a timely manner");
            } else {
                return ResponseData.error("密码已过期" + overDays + "天，请及时修改密码！");
            }
        }

        return ResponseData.success();
    }

    @Override
    public void ssoAdd(SysUserParam sysUserParam) {
        String accountEn = sysUserParam.getAccount();
        String pwdEn = sysUserParam.getPassword();
        // RAS2048解密
        try {
            sysUserParam.setAccount(new String(decrypt(Base64.getDecoder().decode(accountEn), Constant.PRIVATE_KEY)));
            sysUserParam.setPassword(new String(decrypt(Base64.getDecoder().decode(pwdEn), Constant.PRIVATE_KEY)));
        } catch (Exception e) {
            e.printStackTrace();
            throw new AuthException(AuthExceptionEnum.DECRYPT_ERROR);
        }

        checkParam(sysUserParam, false);

        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(sysUserParam, sysUser);
        SysUserFactory.fillAddCommonUserInfo(sysUser);
        sysUser.setPassword(BCrypt.hashpw(sysUser.getPassword(), BCrypt.gensalt()));
        this.save(sysUser);
        sysUserRoleService.grantRole(sysUserParam);
    }

    @Override
    public void ssoUpdate(SysUserParam sysUserParam) {
        this.updateInfo(sysUserParam);
        sysUserRoleService.grantRole(sysUserParam);
    }

    @Override
    public void ssoDelete(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        //不能删除超级管理员
        if (AdminTypeEnum.SUPER_ADMIN.getCode().equals(sysUser.getAdminType())) {
            throw new ServiceException(SysUserExceptionEnum.USER_CAN_NOT_DELETE_ADMIN);
        }
        sysUser.setStatus(CommonStatusEnum.DELETED.getCode());
        this.updateById(sysUser);
        Long id = sysUser.getId();
        //删除该用户对应的用户-角色表关联信息
        sysUserRoleService.deleteUserRoleListByUserId(id);

        // 撤销证书
        if (StringUtils.isNotBlank(sysUser.getCertificatePath())){
            CertAuthUtil.revokeCert(sysUser.getCertificatePath());
        }
    }
}
